#ifndef _MTF_H_
#define _MTF_H_

class MTF
{
	private:
		static unsigned char alphabet[256];

	public:
		static void Encode(const unsigned char  * /*[in]*/data, unsigned int /*[in]*/bytes, unsigned char  * /*[out]*/encoded)
		{
			// MTF encoding
			//  - example: "swm siisss" -->  C=(3,4,4,3,3,4,0,1,0,0) / alphabet=( ,i,m,s,w)
			//
			// Positions of characters are saved in the alphabet array and indices are those characters.
			//
			// reset alphabet order
			for(int a = 0; a < 256; a++)
				alphabet[a] = (unsigned char)a;
			//
			if(bytes > 0)
			{
				unsigned char pos;
				unsigned int enc_len = 0;
				for(unsigned int i = 0; i < bytes; i++)
				{
					pos = alphabet[data[i]];
					encoded[enc_len++] = pos;
					// update alphabet order
					for(int a = 0; a < 256; a++)
						if(alphabet[a] < pos)	// shift all characters between position 0 and pos
							alphabet[a] += 1;
						else if(alphabet[a] == pos)
							alphabet[a] = 0;	// set the current character as first
				}
			}
		}

		static void Decode(const unsigned char  * /*[in]*/data, unsigned int /*[in]*/bytes, unsigned char  * /*[out]*/decoded)
		{
			// MTF decoding
			//  - example: C(3,4,4,3,3,4,0,1,0,0) --> "swm siisss" / alphabet=( ,i,m,s,w)
			//
			// Characters are saved in the alphabet array and indices are positions (C).
			//
			// reset characters order
			for(int a = 0; a < 256; a++)
				alphabet[a] = (unsigned char)a;
			//
			if(bytes > 0)
			{
				unsigned char c;
				for(unsigned int i = 0; i < bytes; i++)
				{
					c = alphabet[data[i]];
					decoded[i] = c;
					// update alphabet order
					for(int a = data[i]; a > 0; a--)	// classic movement of elements in an array
						alphabet[a] = alphabet[a-1];
					alphabet[0] = c;	// set the current character at `data[i]` position
				}
			}
		}
};

#endif	// _MTF_H_